#include <iostream>
#include <string>
#include <vector>
#include<queue>
#include "log.hpp"
#include "cond.hpp"
#include "Mutex.hpp"
#include "Thread.hpp"

namespace ThreadPoolModule
{
    using namespace CondNamespace;
    using namespace MutexNamespace;
    using namespace ThreadModlue;
    using namespace LogModule;

    static const int gnum=5;


    template<class T>
    class ThreadPool
    {
        public:


        void WakeUpAllThread()
        {
            LockGuard lock(_mutex);
            if(_sleepernum)
                _cond.Broadcast();
            LOG(LogLevel::INFO)<<"唤醒所有休眠线程";
        }

        void WakeUpoOne()
        {
            _cond.Signal();
            LOG(LogLevel::INFO)<<"唤醒一个休眠线程";
        }




     
        ThreadPool(int num=gnum)
        :_num(num),
        _isrunning(false),
        _sleepernum(0)
        {
            for(int i=0;i<num;i++)
            {
                _threads.emplace_back(
                    [this](){
                        HandlerTask();
                    }
                );
                
            }
        }

        void Start()
        {
            if(_isrunning)
                return;
            _isrunning=true;
            for(auto& x:_threads)
            {
                x.Start();
                LOG(LogLevel::INFO)<<"start new thread success";
            }
        }


        void Stop()
        {
            if(!_isrunning)
                return;
            _isrunning=false;
            WakeUpAllThread();
        }

        void Join()
        {
            for(auto& thrad:_threads)
            {
                thrad.Join();
            }
        }


        void HandlerTask()
        {
            char name[128];
            pthread_getname_np(pthread_self(),name,sizeof(name));
            while(true)
            {
                T t;

                {
                    LockGuard lock(_mutex);
                    if(_taskq.empty() && _isrunning)
                    {
                        _sleepernum++;
                        _cond.Wait(_mutex);
                        _sleepernum--;
                    }
                    if(!_isrunning && _taskq.empty())
                    {
                        LOG(LogLevel::INFO)<<name<<"退出了，线程池退出或者任务队列为空";
                        break;
                    }

                    t=_taskq.front();
                    _taskq.pop();
                }
                //t();
            }



        }



        bool Enqueue(const T& in)
        {
            if(_isrunning)
            {
                LockGuard lock(_mutex);
                _taskq.push(in);
                if(_threads.size()==_sleepernum)
                {
                    WakeUpoOne();
                }
                return true;
            }
            return false;
        }
        ~ThreadPool()
        {
            
        }







        private:
        std::vector<Thread> _threads;
        int _num;
        std::queue<T> _taskq;
        Cond _cond;
        Mutex _mutex;

        bool _isrunning;
        int _sleepernum;


    };

}
